require "ruby/config.rb"

require "rubygems"

class Array
  def sum
    a = 0
    self.each{|v| a+=v}
    a
  end
end

class LogEntry
  attr_accessor :id,:magnitude,:delta,:catalog, :catalog_id, :time, :alpha, :delta_position, :order_id,  :result_magnitude
  
  def valid?()
    magnitude.to_f < 20 && magnitude.to_f > 5 && (catalog.include?("UCAC2")||catalog.include?("USNO_B10"))
  end
  
  def self.to_type(str,ty)
    str.to_s.split(" ").compact.map{|t| t.send(ty)}
    
  end
  
  def self.create(line_data,time,i)
    r = LogEntry.new
    r.id =to_type(line_data[0],:to_i).first
    r.magnitude,r.delta = to_type(line_data[$CONFIG["input"]["position"]],:to_f)
    r.catalog = to_type(line_data[5],:to_s)
    r.catalog_id = r.catalog[1] if r.valid?
    positions = line_data[1].split(" ")
    r.alpha = positions[0..2].degreefitize.degretize
    r.delta_position = positions[3..5].degreefitize
    r.time = time
    r.order_id = i
    r.covered?
    r
  end
  
  def delta2
    covered? ? delta : 0
  end
  
  def current_libration_position
    position(time)
  end
  
  def covered?
    libration = current_libration_position
    lib_alpha = libration[0]
    lib_delta  =libration[1]
    distance = (((lib_alpha.to_f() - self.alpha.to_f())*cos(self.delta_position.to_rad()))**2 + (lib_delta.to_f() -self.delta_position.to_f())**2)**0.5
    puts distance if  distance< $PRECISION
    distance < $PRECISION
  end
  
end

def get_split_indexes(str)
  str = str.split("")
  result = []
  i = 0
  while(i<str.size)
    result<<i if str[i] == "|"
    i+=1
  end
  result
end

def splitalize(str,indexes)
  i = 0
  while(i < indexes.size && indexes[i] < str.size)
    str.insert(i+indexes[i],",") rescue nil
    i+=1
  end
  str.split(",").map{|t| t.strip}
end



def load(history,name,id)
  accept=false
  content = nil
  lines = []

  content = File.open("#{$CONFIG["input"]["path"]}/#{name}"){|f| f.read}
  time = nil
  content.split("\n").each do |line|
    if line.include?("Mid-exposure time")
       time = line.gsub("Mid-exposure time:","").split(" ").compact[1]
    end
    
    accept  = false if line.scan(/^Mean/).any?
    if(accept)
      lines<<line
    end
    accept = true if line.scan(/Catalog of objects/).any?
  end
  lines = lines.map{|s| s.strip}.select{|t| t.scan(/----/).empty?}.compact
  
  indexes  = get_split_indexes(lines.first)
  lines  = lines - [lines[0],lines[1],lines[2]]
  lines = lines.map{|t| LogEntry.create(splitalize(t,indexes),time,id) }.select{|t| t.valid?}.each do |t|
    history[t.catalog_id]||=[]
    history[t.catalog_id]<<t
  end
end

def output_path
  $CONFIG["output"]["path"]
end

def produce_table(hash)
  `rm #{output_path}/*`
  hash.keys.sort.each do |k|
    File.open("#{output_path}/#{k}.dat","w") do |f|
      hash[k].each_with_index do |a,b|
        patch_observation(a,hash)
        if ($CONFIG['input']['normalize'])
          f.write("#{a.order_id}, #{a.result_magnitude}, #{a.delta2}\n")
        else
          f.write("#{a.order_id}, #{a.magnitude}, #{a.delta2}\n")
        end
        
      end
    end 
  end
  
end

def publish
  `ls #{output_path} | grep dat`.split("\n").each do |f|
     cmd="set terminal png\n set yrange [#{$CONFIG["plot"]["yrange"]["min"]}:#{$CONFIG["plot"]["yrange"]["max"]}]\n plot '#{output_path}/#{f}' title '#{$CONFIG["plot"]["title"]}'   with errorbars, \"\" smooth csplines t '#{$CONFIG["plot"]["curve"]}' \n"
     File.open("plot.cmd","w"){|file| file.write(cmd)}
     `gnuplot plot.cmd > #{output_path}/#{f}.png`
   end
end


def all_observations_from(id,hash)
  result = {}
  all_stars(hash).each do |star|
    observation = observation_for_at(star,id,hash)
    result[star] = observation if observation
  end
  result
end

def all_stars(hash)
  hash.keys
end

def all_observations_for(id,hash)
  hash[id]
end

def observation_for_at(id,field_id,hash)
  hash[id].select{|t| t.order_id = field_id}.first
end

def all_fields(hash)
  hash.values.flatten.map{|t| t.order_id}.max
end


def kosher_star
  $CONFIG['input']['kosher_star']
end

def kosher_average(hash)
   $kosher_average||=star_average(kosher_star,hash)
end

def kosher_observation(id,hash)
  kosher_observation = all_observations_for(kosher_star,hash).select{|s| s.order_id = id}.first || kosher_average(hash)
end

def star_average(star,history)
  observations = all_observations_for(star,history)
  observations.map{|s| s.magnitude}.sum/observations.size
end

def patch_observation(obs,history)
  star_avg = star_average(obs.catalog_id,history)
  obs.result_magnitude = obs.magnitude/star_avg - kosher_observation(obs.order_id,history).magnitude/kosher_average(history)
end



def full_load
  history = {}
  `ls #{$CONFIG["input"]["path"]} | grep proclog`.split("\n").each_with_index do |t,i|
    load(history,t,i)
  end
  produce_table(history)
end

full_load
publish

